import org.spockframework.compiler.model.ExpectBlock;

import spock.lang.Shared;
import spock.lang.Specification;


class DiffTests extends Specification {

	
	@Shared def srcDir = 'test-dir/src-dir'
	@Shared def localDir = 'test-dir/local-dir'
	@Shared def diffDir = 'test-dir/diff-dir'
	
	@Shared def diff = new Diff(srcDir, localDir, diffDir)
	
	def "new added file should be copied"() {
		given :
			def file1 = createNewFile(srcDir)
		
		when :	diff.doDiff()
		
		then : "file is copied to local dir and diff dir contains copied file with suffix .added"
			fileShouldBeCopied(file1, localDir)
			fileShouldBeCopiedWithSuffix(file1, diffDir, '.added')		
	}
	
	def "new added file in sub folder should be copied"() {
		given :
			def subFolder = createSubFolder(srcDir)
			assert subFolder.isDirectory()
			def file1 = createNewFile(subFolder)
		
		when :	diff.doDiff()
		
		then : "file is copied to local dir and diff dir contains copied file with suffix .added"
			fileShouldBeCopied(file1, localDir)
			fileShouldBeCopiedWithSuffix(file1, diffDir, '.added')
	}
	
	def createSubFolder(dir) {
		def subFolder = new File(dir, "subFolder")
		subFolder.mkdir()
		
		subFolder
	}
	
	def "already copied and not changed file should not be copied"() {
		given :
			def file1 = createNewFile(srcDir)
			Diff.copyFile(file1, diff.getLocalFile(file1))
		
		when : diff.doDiff()
		
		then : "diff dir should be empty because no file is copied"
			new File(diffDir).list().length == 0
	}
	
	def "changed file should be copied"() {
		given :
			def file1 = createNewFile(srcDir)
			Diff.copyFile(file1, diff.getLocalFile(file1))
			file1 << "changed text"
		
		when : diff.doDiff()
		
		then : "changed file should be copied to local dir and diff dir"
			fileShouldBeCopied(file1, localDir)
			fileShouldBeCopied(file1, diffDir)
	}
	
	def "changed file in sub folder should be copied"() {
		given :
			def subFolder = createSubFolder(srcDir)
			def file1 = createNewFile(subFolder)
			Diff.copyFile(file1, diff.getLocalFile(file1))
			file1 << "changed text"
		
		when : diff.doDiff()
		
		then : "changed file should be copied to local dir and diff dir"
			fileShouldBeCopied(file1, localDir)
			fileShouldBeCopied(file1, diffDir)
	}
	
	def "deleted file should be deleted"() {
		given :
			def file1 = createNewFile(srcDir)
			def localFile = diff.getLocalFile(file1)
			Diff.copyFile(file1, localFile)
			assert localFile.exists()
			assert file1.delete()
	
		when : diff.doDiff()
	
		then : "deleted file should be deleted from local dir and new empty file with suffix .deleted is created in diff dir"
			!localFile.exists()
			deletedFileCreatedInDiffDir(file1, diffDir)
	}
	
	def "deleted file in sub folder should be deleted"() {
		given :
			def subFolder = createSubFolder(srcDir)
			def file1 = createNewFile(subFolder)
			def localFile = diff.getLocalFile(file1)
			Diff.copyFile(file1, localFile)
			assert localFile.exists()
			assert file1.delete()
	
		when : diff.doDiff()
	
		then : "deleted file should be deleted from local dir and new empty file with suffix .deleted is created in diff dir"
			!localFile.exists()
			deletedFileCreatedInDiffDir(file1, diffDir)
	}
	
	void deletedFileCreatedInDiffDir(file, dir) {
		def path = file.absolutePath - new File(srcDir).absolutePath + '.deleted'
		def deletedFile = new File(dir, path)
		assert deletedFile.exists()
		assert deletedFile.text == ''
	}
	
	def cleanup() {
		removeAllFiles(srcDir)
		removeAllFiles(localDir)
		removeAllFiles(diffDir)
	}
	
	def removeAllFiles(dir) {
		def theDir = new File(dir)
		theDir.eachFile {file ->
			if (file.isFile())
				file.delete()
			else {
				removeAllFiles(file.absolutePath)
				file.deleteDir()
			}
		}
	}
	
	void fileShouldBeCopied(file, destDir) {
		def file2 = new File(Diff.replacePath(file.absolutePath, srcDir, destDir))
		assert file2.exists()
		assert file2.lastModified() == file.lastModified() 
		assert file2.text == file.text
	}
	
	void fileShouldBeCopiedWithSuffix(file, destDir, suffix) {
		def file2 = new File(destDir, file.absolutePath - new File(srcDir).absolutePath + suffix)
		assert file2.exists() 
		assert file2.text == file.text
	}
	
	def createNewFile(dir) {
		def name = '' + System.currentTimeMillis()
		def file = new File(dir, name)
		file.createNewFile()
		file << name
		
		file
	}
}
